#include <asio.hpp>  // 引入 ASIO 库
#include <boost/uuid/uuid.hpp>  // 引入 Boost UUID 库
#include <boost/uuid/uuid_generators.hpp>  // 引入 Boost UUID 生成器
#include <boost/uuid/uuid_io.hpp>  // 引入 Boost UUID 输入输出流
#include <nlohmann/json.hpp>  // 引入 JSON 库
#include <iostream>  // 引入输入输出流
#include "udp_punchthrough.hpp"  // 引入 UDP 打洞头文件
#include "udp_communication.hpp"  // 引入 UDP 通信头文件

using asio::ip::udp;  // 使用 UDP 协议
using json = nlohmann::json;  // 定义 JSON 类型

// 发送 JSON 请求到服务器
void send_json_request(json j) {
	asio::io_context io;
	asio::ip::tcp::resolver resolver(io);  // 解析目标地址
	auto endpoints = resolver.resolve("127.0.0.1", "9000");  // 连接到服务器（本地地址，端口9000）
	asio::ip::tcp::socket socket(io);  // 创建一个 TCP socket
	asio::connect(socket, endpoints);  // 连接到服务器

	// 将请求转换为字符串，并发送到服务器
	std::string msg = j.dump() + "\n";
	asio::write(socket, asio::buffer(msg));

	// 接收服务器返回的信息
	asio::streambuf buf;  // 用于接收响应
	asio::read_until(socket, buf, "\n");  // 读取直到换行符
	std::istream input(&buf);  // 创建输入流
	std::string response;
	std::getline(input, response);  // 获取响应内容
	json result = json::parse(response);  // 解析 JSON 响应
	std::cout << "Response: " << result.dump(4) << std::endl;
}

int main() {
    // 生成客户端的 UUID
    boost::uuids::random_generator generator;
    boost::uuids::uuid uuid = generator();
    std::string my_uuid = boost::uuids::to_string(uuid);
    std::cout << "My UUID: " << my_uuid << std::endl;

    // 创建注册消息
    json reg_msg = {
        {"type", "register"},
        {"uuid", my_uuid}  // 客户端的 UUID
    };
    send_json_request(reg_msg);  // 发送注册请求

    // 查询其他客户端的信息（例如 UUID 为 "B-456" 的客户端）
    std::string target = "B-456";
    json query_msg = {
        {"type", "query"},
        {"target", target}  // 查询目标 UUID
    };
    send_json_request(query_msg);  // 发送查询请求

    // 开始 UDP 打洞
    std::string target_ip = "127.0.0.1";  // 目标 IP（这里为本地地址）
    unsigned short target_port = 9001;   // 目标端口
    asio::io_context io_context;
    UDPPunchthroughClient udp_client(io_context, target_ip, target_port);
    udp_client.start();  // 启动打洞过程

    // 开始通信，假设端口 9002 用于通信
    unsigned short local_port = 9002;
    UDPCommunicationClient communication_client(io_context, local_port, target_ip, target_port);
    communication_client.start();  // 启动通信

    return 0;
}